package utils;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.extractor.WordExtractor;
import org.apache.poi.hwpf.usermodel.Range;
import org.apache.poi.ooxml.POIXMLDocument;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

//import org.apache.poi.xwpf.usermodel.*;

public class InsertAndOutWordUtils {

    private static final Logger log = LoggerFactory.getLogger(InsertAndOutWordUtils.class);

    /**
     * word内容替换-不添加换行符
     * @param templateFilePath 替换文件所在路径
     * @param formart  替换文件扩展名
     * @param map      替换数据集合
     * @description: 替换word中的文字
     * @author: Mr.Jkx
     * @time: 2023/1/10 13:19
     */
    public static void wordTextSubstitution(String templateFilePath,String outFilePath, String formart, Map<String,String> map) {
        if ("DOCX".equals(formart)) {
//            WordDocxReplaceUtils.docxReplace(templateFilePath,outFilePath,map);

            WordDocxReplaceUtils.docxPoiReplace(templateFilePath, outFilePath, ObjectToMapUtils.templateDataKeyHashMapToKey(map));
        } else if ("DOC".equals(formart)) {
            WordDocReplaceUtils.docxReplace(templateFilePath,outFilePath,map);
        }
    }

    /**
     * word内容替换-并添加换行符
     * @param templateFilePath 替换文件所在路径
     * @param formart  替换文件扩展名
     * @param map      替换数据集合
     * @description: 替换word中的文字
     * @author: Mr.Jkx
     * @time: 2023/1/10 13:19
     */
    public static boolean wordTextSubstitutionTwo(String templateFilePath,String outFilePath, String formart, Map<String, String> map) {
        boolean flag = false;

        String textPath = "";
        File file = new File(templateFilePath);
        if (!file.exists()){
            log.error("替换文件失败，文件不存在");
            return false;
        }

        String fileName = file.getName();
        try {
            if ("DOCX".equals(formart)) {
                XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(templateFilePath));
                // 替换段落中的指定文字
                Iterator<XWPFParagraph> itPara = document.getParagraphsIterator();

                while (itPara.hasNext()) {
                    XWPFParagraph paragraph = itPara.next();
                    List<XWPFRun> runs = paragraph.getRuns();
                    for (int i = 0; i < runs.size(); i++) {
                        String oneparaString = runs.get(i).getText(runs.get(i).getTextPosition());
                        if (oneparaString != null) {
                            boolean reFlag = false;
                            for (Map.Entry<String, String> entry : map.entrySet()) {
                                if (!oneparaString.contains(entry.getKey())){
                                    continue;
                                }
                                if (StringUtils.isNotBlank(entry.getValue()) && entry.getValue().contains("\n")) {
                                    String[] lines = entry.getValue().split("\n");
                                    runs.get(i).setText(lines[0], 0); // 替换第一行

                                    for (int j = 1; j < lines.length; j++) {
//                                        System.out.println("paragraph==========>"+j);
                                        // 添加新的文本行，并设置换行格式
                                        XWPFParagraph newParagraph = document.createParagraph();
                                        XWPFRun newRun = newParagraph.createRun();
                                        newRun.setText(lines[j]);
                                        newRun.addBreak();
                                    }
                                }else {
                                    reFlag = true;
                                    oneparaString = oneparaString.replace(entry.getKey(), entry.getValue());
                                }
                            }

                            if (reFlag) {
                                runs.get(i).setText(oneparaString, 0);
                            }
                        }
                    }
                }

                /**
                 * 替换表格中的指定文字
                 */
                Iterator<XWPFTable> itTable = document.getTablesIterator();
                while (itTable.hasNext()) {
                    XWPFTable table = (XWPFTable) itTable.next();
                    int count = table.getNumberOfRows();
                    for (int i = 0; i < count; i++) {
                        XWPFTableRow row = table.getRow(i);
                        List<XWPFTableCell> cells = row.getTableCells();
                        for (XWPFTableCell cell : cells) {
                            for (XWPFParagraph p : cell.getParagraphs()) {
                                for (XWPFRun r : p.getRuns()) {
                                    String text = r.getText(0);
//                                    log.info("遍历该段里的所有文本-{}",text);
                                    for (Map.Entry<String, String> e : map.entrySet()) {
                                        if (text != null && text.contains(e.getKey())) {

                                            if (StringUtils.isNotBlank(e.getValue()) && e.getValue().contains("\n")){
//                                                System.out.println("table--: "+e.getValue());

                                                // 清空原先文本，使用换行后的新文本
                                                String[] lines = e.getValue().split("\n");
                                                r.setText("", 0);
                                                for (int j = 0; j < lines.length; j++) {
//                                                    System.out.println("table==========>"+j);
                                                    if (j > 0){
                                                        r.addCarriageReturn(); // 换行
                                                    }
                                                    r.setText(lines[j]);


                                                }

                                            }else {

//                                                log.info("key-{}", e.getValue());
                                                text = text.replace(e.getKey(), e.getValue());
                                                r.setText(text, 0);
                                            }
                                        }
                                    }
                                }
                            }

                        }
                    }
                }
//                replaceTableValue(document,map);


                // 创建新文件存放新内容
                FileOutputStream outStream = new FileOutputStream(outFilePath);
                document.write(outStream);
                outStream.close();

                flag = true;

                log.info("----替换word文档内容success---");
            } else if ("DOC".equals(formart)) {

                HWPFDocument document = new HWPFDocument(new FileInputStream(templateFilePath));
                Range range = document.getRange();
                for (Map.Entry<String, String> entry : map.entrySet()) {
                    range.replaceText(entry.getKey(), entry.getValue());
                }
                // 创建新文件存放新内容
                FileOutputStream outStream = new FileOutputStream(outFilePath);
                document.write(outStream);
                outStream.close();

                flag = true;

                log.info("----替换word文档内容success---");
            }
        } catch (Exception e) {
            log.error("替换word里面的内容出错-{}", e);
        }

        return flag;
    }

    public void thWord(XWPFDocument document,Map<String, String> map){
        //获取表格
        List<XWPFTable> tables=document.getTables();
        //定位到第一个表格
        XWPFTable table=tables.get(0);
        //遍历该表格所有的行
        for(int i=0;i<table.getRows().size();i++) {
            XWPFTableRow row=table.getRow(i);
            //遍历该行所有的列
            for(int j=0;j<row.getTableCells().size();j++) {
                XWPFTableCell cell=row.getTableCells().get(j);
                //获取该格子里所有的段
                List<XWPFParagraph> paragraphs=cell.getParagraphs();
                for(XWPFParagraph p:paragraphs) {
                    //遍历该格子里的段
                    List<XWPFRun> runs=p.getRuns();
                    for(XWPFRun run:runs) {
                        //遍历该段里的所有文本
                        String str=run.toString();
                        System.out.println(str);
                        log.info("遍历该段里的所有文本-{}",str);

                        //如果该段文本包含map中的key，则替换为map中的value值。
                        Set<String> keySet = map.keySet();
                        for(String key:keySet){
                            if(str.trim().equals(key)){
                                System.out.println("key"+map.get(key));
                                log.info("key-{}",map.get(key));

                                //替换该文本0位置的数据。
                                run.setText(map.get(key),0);

                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 获取文档里面的内容
     * @param url 路径
     * @param formart 文档类型
     * @return
     */
    public static String getWordText(String url,String formart){
        File file = new File(url);
        if (!file.exists()){
            log.error("文件不存在");
            return "文件不存在";
        }
        FileInputStream fis = null;
        XWPFDocument document = null;
        XWPFWordExtractor extractor = null;
        String msg = "";
        try {
            fis = new FileInputStream(file);
            if (formart.equals(".docx")) {
//            if (FileMagic.valueOf(fis) == FileMagic.OOXML && formart.equals(".docx")) {
                document = new XWPFDocument(fis);
                extractor = new XWPFWordExtractor(document);
                msg = extractor.getText();
                extractor.close();
                document.close();
            }else if (formart.equals(".doc")){
//            }else if (FileMagic.valueOf(fis) == FileMagic.OLE2 && formart.equals(".doc")){
                WordExtractor ex = new WordExtractor(fis);
                msg = ex.getText();
                ex.close();
            }else {
                log.info("该文件不是word文件【{}】",formart);
            }
        } catch (Exception e) {
            log.error("获取【{}】类型的word文档内容出错-{}",formart,e);
        }finally {
            try {
                fis.close();
            } catch (IOException e) {
                log.error("关闭文件出错【IOException】-{}",e);
            }
        }
        return msg;
    }

    public static void replaceTableValue(XWPFDocument document, Map<String, String> textMap){
        Iterator<XWPFTable> it = document.getTablesIterator();
        //表格内容替换添加
        while(it.hasNext()){
            XWPFTable table = it.next();
            int rcount = table.getNumberOfRows();
            for(int i =0 ;i < rcount;i++){
                XWPFTableRow row = table.getRow(i);
                List<XWPFTableCell> cells =  row.getTableCells();
                for (XWPFTableCell cell : cells){
                    for(Map.Entry<String, String> e : textMap.entrySet()){
                        if(checkText(cell.getText())){
                            List<XWPFParagraph> tableParagraphsList = cell.getParagraphs();
                            for (XWPFParagraph paragraph : tableParagraphsList) {
                                String text = paragraph.getText(); //获取到段落中的所有文本内容
                                if (checkText(text)) { //判断此段落中是否有需要进行替换的文本
                                    List<XWPFRun> runs = paragraph.getRuns();
                                    for (XWPFRun run : runs) {
                                        run.setText(changeValue(run.toString(), textMap), 0);//替换模板原来位置
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 判断文本中是否包含$
     *
     * @param text 文本
     * @return 包含返回true, 不包含返回false
     */
    public static boolean checkText(String text) {
        boolean check = false;
        if (text.contains("{")) {
            check = true;
        }
        if (text.contains("}")) {
            check = true;
        }
        return check;
    }

    /**
     * 匹配传入信息集合与模板
     *
     * @param value   模板需要替换的区域
     * @param textMap 传入信息集合
     * @return 模板需要替换区域信息集合对应值
     */
    public static String changeValue(String value, Map<String, String> textMap) {
        System.out.println(value+"::");
        Set<Map.Entry<String, String>> textSets = textMap.entrySet();
        for (Map.Entry<String, String> textSet : textSets) {
            //匹配模板与替换值 格式${key}
            String key = textSet.getKey();
            System.out.println(key);
            if (value.contains(key)) {
                value = textSet.getValue();
            }
        }
        //模板未匹配到区域替换为空
        if (checkText(value)) {
            value = "";
        }
        return value;
    }

    /**
     * word内容替换-不添加换行符
     * @param templateFilePath 替换文件所在路径
     * @param formart  替换文件扩展名
     * @param map      替换数据集合
     * @description: 替换word中的文字
     * @author: Mr.Jkx
     * @time: 2023/1/10 13:19
     */
    public static void wordTextSubstitutionOld(String templateFilePath,String outFilePath, String formart, Map<String, String> map) {
        String textPath = "";
        File file = new File(templateFilePath);
        if (!file.exists()){
            log.error("替换文件失败，文件不存在");
            return;
        }
        String fileName = file.getName();
        try {
            if ("DOCX".equals(formart)) {
//                if (fileName != null && fileName != "") {
//                    String name = fileName.substring(0, fileName.length() - 5);
//                    textPath = filePath.replaceAll(fileName, name + "_" + System.currentTimeMillis() + ".docx");
//                }
                XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(templateFilePath));
                // 替换段落中的指定文字
                Iterator<XWPFParagraph> itPara = document.getParagraphsIterator();

                while (itPara.hasNext()) {
                    XWPFParagraph paragraph = itPara.next();
                    List<XWPFRun> runs = paragraph.getRuns();
                    for (int i = 0; i < runs.size(); i++) {
                        String oneparaString = runs.get(i).getText(runs.get(i).getTextPosition());
                        if (oneparaString != null) {
                            for (Map.Entry<String, String> entry : map.entrySet()) {
                                oneparaString = oneparaString.replace(entry.getKey(), entry.getValue());
                            }
                            runs.get(i).setText(oneparaString, 0);
                        }
                    }
                }

                /**
                 * 替换表格中的指定文字
                 */
                Iterator<XWPFTable> itTable = document.getTablesIterator();
                while (itTable.hasNext()) {
                    XWPFTable table = (XWPFTable) itTable.next();
                    int count = table.getNumberOfRows();
                    for (int i = 0; i < count; i++) {
                        XWPFTableRow row = table.getRow(i);
                        List<XWPFTableCell> cells = row.getTableCells();
                        for (XWPFTableCell cell : cells) {
                            for (XWPFParagraph p : cell.getParagraphs()) {
                                for (XWPFRun r : p.getRuns()) {
                                    String text = r.getText(0);
                                    log.info("遍历该段里的所有文本-{}",text);
                                    for (Map.Entry<String, String> e : map.entrySet()) {
                                        if (text != null && text.contains(e.getKey())) {
                                            log.info("key-{}",e.getValue());
                                            text = text.replace(e.getKey(), e.getValue());
                                            r.setText(text, 0);
                                        }
                                    }
                                }
                            }

                        }
                    }
                }
//                replaceTableValue(document,map);

                // 创建新文件存放新内容
                FileOutputStream outStream = new FileOutputStream(outFilePath);
                document.write(outStream);
                outStream.close();

                log.info("----替换word文档内容success---");
            } else if ("DOC".equals(formart)) {
//                if (fileName != null && fileName != "") {
//                    String name = fileName.substring(0, fileName.length() - 4);
//                    textPath = filePath.replaceAll(fileName, name + "_" + System.currentTimeMillis() + ".doc");
//                }
                HWPFDocument document = new HWPFDocument(new FileInputStream(templateFilePath));
                Range range = document.getRange();
                for (Map.Entry<String, String> entry : map.entrySet()) {
                    range.replaceText(entry.getKey(), entry.getValue());
                }
                // 创建新文件存放新内容
                FileOutputStream outStream = new FileOutputStream(outFilePath);
                document.write(outStream);
                outStream.close();

                log.info("----替换word文档内容success---");
            }
        } catch (Exception e) {
            log.error("替换word里面的内容出错-{}", e);
        }
    }

}
